iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0
Modern Web

30 天掌握 React & Next.js:從基礎到面試筆記系列 第 7

Day 7 : 為什麼不要直接修改 state ?

  • 分享至 

  • xImage
  •  

在 React 裡,你常常聽到「不要直接修改 state」。
真正的原因是:React 偵測不到你直接改了內容

React 如何判斷 state 是否改變?

React 的運作方式是:

  • Primitive (原始型別:number, string, boolean) → React 比較值是否一樣。
  • Reference type (物件、陣列) → React 比較 reference(記憶體位址)是否一樣。

所以 React 不會深度比對物件的每個欄位,只會檢查「你是不是給了我一個新值或新的 reference」。

Primitive 範例

const [count, setCount] = useState(0);

// 更新為新值 → React 偵測到改變 → re-render
setCount(1);

// 設定成相同的值 → React 偵測不到改變 → 不 re-render
setCount(1);

👉 對 primitive 來說,這樣很直觀:值不同就 re-render,值相同就跳過。

Reference 範例

const [user, setUser] = useState({ name: "Andy" });

// ❌ 錯誤:直接修改
user.name = "Jack";
setUser(user); // reference 沒變 → React 偵測不到 → 不 re-render

// ✅ 正確:建立新物件
setUser({ ...user, name: "Jack" }); // 新 reference → React 偵測到 → re-render

👉 對 reference 來說,React 只比較 reference(物件位址)。
如果你只是改了裡面的屬性,reference 沒變,React 會覺得「沒改」。

常見誤解

  • 誤解 1:因為 call by reference 才不能直接改
    ❌ 錯。真正的原因是 React 只檢查 reference,不會深度比對。
  • 誤解 2:不可變更新會很慢
    其實成本很小,而且換來的是正確 re-render 與效能優化(例如 React.memo)。

實務應用

  • 陣列:setTodos([...todos, newTodo])
  • 物件:setUser({ ...user, age: 26 })

面試回答

中文

React 判斷 state 是否改變,是透過比較值或 reference。
Primitive 值不同就 re-render;值相同就跳過。
物件/陣列只看 reference,如果直接改內容 reference 沒變,React 偵測不到。
所以我們要用不可變語法,建立新物件或陣列,確保 React 偵測到變化。

總結

  • Primitive state → React 比較值。
  • Reference state → React 比較 reference,不會深度比對內容。
  • 直接修改物件或陣列 → reference 沒變,React 偵測不到。
  • 不可變語法 建立新 reference,才能正確 re-render。

上一篇
Day 6:為什麼在 React list 中 key 這麼重要?
下一篇
Day 8:React Hook 是什麼?Hook 解決了哪些問題?
系列文
30 天掌握 React & Next.js:從基礎到面試筆記22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言